package com.sunlands.zlcx.usercenter.service;

import com.sunlands.zlcx.usercenter.repository.UsersLearnTimingRepository;
import com.sunlands.zlcx.usercenter.util.DataFormat;
import com.sunlands.zlcx.usercenter.util.DateUtil;
import com.sunlands.zlcx.usercenter.util.EntityUtils;
import com.sunlands.zlcx.usercenter.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author zhaocg
 * @create 2019/8/7 12:36
 */
@Service
@Slf4j
public class DurationSummaryServiceImpl {

    @Autowired
    private UsersLearnTimingRepository learnTimingRepository;

    @Autowired
    @Lazy
    private UsersServiceImpl usersService;


    /**
     * 获取当天的打卡信息
     *
     * @param userId
     * @return
     */
    public PersonalShowSummaryVO getDurationSummary(Long userId){

        long beginDate = System.currentTimeMillis();
        log.info("用户信息 userId={}" , userId);
        PersonalShowSummaryVO showSummary = new PersonalShowSummaryVO();
        List<PersonalSummaryVO> summaryVOS = learnTimingRepository.findDurationSummary(userId);

        if ( !CollectionUtils.isEmpty(summaryVOS) ) {
            showSummary.setSumMinutes(summaryVOS.get(0).getSumMinutes());
            showSummary.setFrequency(summaryVOS.get(0).getFrequency());
        }

        List<PersonalTotalSummaryVO> totalSummaryVOS = learnTimingRepository.findTotalDurationSummary(userId);
        if ( !CollectionUtils.isEmpty(totalSummaryVOS) ) {
            showSummary.setTotalFrequency(totalSummaryVOS.get(0).getTotalFrequency());
            showSummary.setTotalSumMinutes(totalSummaryVOS.get(0).getTotalSumMinutes());
        }

        Long days = getDaysByUserCreateTime(userId);
        if ( days != null && days != 0 ) {
            Double average = DataFormat.divideLongScaleDecimals(showSummary.getTotalSumMinutes() , days , 2);
            showSummary.setAvgSumMinutes(average);
        }

        log.info("获取用户当天打卡信息data=[{}] , 时长={}ms" , showSummary , System.currentTimeMillis() - beginDate);
        return showSummary;
    }

    /**
     * 根据用户ID以及以及日期偏移量查询昨天、近7天、近30天的数据
     *
     * @param userId
     * @param delay
     * @return
     */
    public List<PersonalSummaryDateVO> findDurationSummaryList(Long userId , String delay){

        long beginDate = System.currentTimeMillis();

        //获取偏移量天数的的日期
        Date beginTime = DateUtil.strToDate(DateUtil.getNextDay(DateUtil.dateToStr(new Date()) , delay));
        //结束时间均为到昨天结束
        Date endTime = DateUtil.strToDate(DateUtil.getNextDay(DateUtil.dateToStr(new Date()) , "-1"));
        log.info("用户ID={} 查询日期区间：startTime={} , endTime={}" , userId ,beginTime , endTime);
        List<PersonalSummaryDateVO> summaryDate = new ArrayList<>();
        summaryDate = learnTimingRepository.findDurationSummaryList(userId, beginTime , endTime);
        log.info("获取{}天数据 data={} , 时长={}ms" ,delay, summaryDate , System.currentTimeMillis() - beginDate);
        return summaryDate;

    }

    /**
     * 根据起始、结束时间获取打卡数据
     *
     * @param userId
     * @param startTime
     * @param endTime
     * @return
     */
    public List<PersonalSummaryDateVO> findDurationSummaryListByDates(Long userId , Date startTime , Date endTime){

        long beginDate = System.currentTimeMillis();
        log.info("用户ID={} 查询日期区间：startTime={} , endTime={}" , userId ,startTime , endTime);
        List<PersonalSummaryDateVO> summaryDate = new ArrayList<>();
        summaryDate = learnTimingRepository.findDurationSummaryList(userId, startTime , endTime);
        log.info("根据日期查询用户打卡情况 data={} , 时长={}ms" ,summaryDate , System.currentTimeMillis() - beginDate);
        return summaryDate;

    }

    /**
     * 获取排行信息
     *
     * @param delay
     * @return
     */
    public DurationShowSummaryVO getLeaderBoardDurationSummary(Long userId , String delay) throws Exception{

        long beginDate = System.currentTimeMillis();
        List<DurationShowSummaryVO> showSummaryVOList = new ArrayList<>();
        UsersVO usersVOBean = usersService.find(userId);
        DurationShowSummaryVO durationShowSummaryVO = new DurationShowSummaryVO();

        if ( usersVOBean != null ) {
            durationShowSummaryVO.setAvatarUrl(usersVOBean.getAvatarUrl());
            durationShowSummaryVO.setName(usersVOBean.getName());
            durationShowSummaryVO.setCurrentLearnTargetName(usersVOBean.getCurrentLearnTargetName());
            durationShowSummaryVO.setUserId(userId);
        }

        //获取偏移量天数的的日期
        Date startTime = DateUtil.strToDate(DateUtil.getNextDay(DateUtil.dateToStr(new Date()) , delay));
        //结束时间均为到昨天结束
        Date endTime = DateUtil.strToDate(DateUtil.getNextDay(DateUtil.dateToStr(new Date()) , "-1"));

        log.info("查询排行 日期区间：startTime={} , endTime={}"  ,startTime , endTime);
        List<Object[]> summaryVOPage = learnTimingRepository.getLeaderBoardDurationSummaryBy(startTime , endTime);
        //List<Object[]> 转换List<DurationSummaryVO>
        List<DurationSummaryVO> summaryVOList = EntityUtils.objectToBean(summaryVOPage , DurationSummaryVO.class);

        if ( CollectionUtils.isEmpty(summaryVOList) ) {
            durationShowSummaryVO.setShowSummaryVOList(showSummaryVOList);
            return durationShowSummaryVO;
        }

        Map<Long, DurationSummaryVO> durationSummaryVOMap = new HashMap<>();

        //设置排行
        AtomicInteger atomicInteger = new AtomicInteger(0);
        summaryVOList.stream().forEach(durationSummaryVO -> {
            atomicInteger.getAndIncrement();
            durationSummaryVO.setLeaderBoard(atomicInteger.intValue());
        });

        durationSummaryVOMap = summaryVOList.stream().collect(Collectors.toMap(x->x.getUserId() , x->x));
        //查询用户数据
        List<Long> userIds = summaryVOList.stream().map(DurationSummaryVO ::getUserId).collect(Collectors.toList());
        List<UsersVO> usersVOList = usersService.findByIdIn(userIds);

        if ( !CollectionUtils.isEmpty(usersVOList) ) {
            //构建新的list
            for ( UsersVO usersVO : usersVOList) {
                if ( usersVO != null && usersVO.getId().equals(userId) ) {
                    DurationSummaryVO currencyPersonalSummaryVO = durationSummaryVOMap.get(usersVO.getId());

                    if ( currencyPersonalSummaryVO != null ) {
                        durationShowSummaryVO.setLeaderBoard(currencyPersonalSummaryVO.getLeaderBoard());
                        durationShowSummaryVO.setSumMinutes(currencyPersonalSummaryVO.getSumMinutes());
                    }
                }
                DurationSummaryVO durationSummaryVO = durationSummaryVOMap.get(usersVO.getId());
                DurationShowSummaryVO showSummaryVO = new DurationShowSummaryVO();
                showSummaryVO.setAvatarUrl(usersVO.getAvatarUrl());
                showSummaryVO.setName(usersVO.getName());
                showSummaryVO.setCurrentLearnTargetName(usersVO.getCurrentLearnTargetName());
                showSummaryVO.setUserId(usersVO.getId());
                if ( durationSummaryVO != null ) {
                    showSummaryVO.setLeaderBoard(durationSummaryVO.getLeaderBoard());
                    showSummaryVO.setSumMinutes(durationSummaryVO.getSumMinutes());
                }
                showSummaryVOList.add(showSummaryVO);
            }
        }
        //只有按照排行进行排序
        durationShowSummaryVO.setShowSummaryVOList(showSummaryVOList.stream().sorted(Comparator.comparing(DurationShowSummaryVO ::getLeaderBoard)).collect(Collectors.toList()));
        log.info("获取{}天数据 data={} , 时长={}ms" ,delay, durationShowSummaryVO , System.currentTimeMillis() - beginDate);

        return durationShowSummaryVO;
    }

    /**
     * 根据用户ID获取用户基本信息
     *
     * @param userId
     * @return
     */
    private Long getDaysByUserCreateTime(Long userId){
        UsersVO usersVO = usersService.find(userId);
        Long days = 0L;
        if ( usersVO != null ) {
            Date createTime = usersVO.getCreateTime();
            //获取注册天数
            String strDays = DateUtil.getTwoDay(DateUtil.dateToStr(new Date()),DateUtil.dateToStr(createTime) );
            days = Long.valueOf(strDays);
        }
        log.info("返回天数为：{}天" , days);
        return days;
    }


}
